package com.yuyou.fn.portal.service.impl;

import com.github.wens.mybatisplus.examples.Example;
import com.google.common.base.Function;
import com.google.common.collect.*;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.educational.entity.CourseClass;
import com.yuyou.fn.educational.entity.StudentReg;
import com.yuyou.fn.educational.service.IContinueClassSuggestionService;
import com.yuyou.fn.educational.service.ICourseClassService;
import com.yuyou.fn.educational.service.IStudentRegService;
import com.yuyou.fn.educational.vo.ContinueClassSuggestResultVo;
import com.yuyou.fn.portal.entity.CourseDisplayConfig;
import com.yuyou.fn.portal.entity.OuterCourseClass;
import com.yuyou.fn.portal.entity.OuterOrder;
import com.yuyou.fn.portal.entity.OuterShoppingcart;
import com.yuyou.fn.portal.service.*;
import com.yuyou.fn.portal.vo.OuterCampus;
import com.yuyou.fn.portal.vo.SuggestResultVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class SuggestionServiceImpl implements ISuggestionService{

    @Resource
    private IContinueClassSuggestionService continueClassSuggestionService;

    @Resource
    private IOuterCourseClassService outerCourseClassService;


    @Resource
    private IOuterShoppingcartService outerShoppingcartService;

    @Resource
    private IOuterCampusService campusService;

    @Resource
    private IOuterOrderService outerOrderService ;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private IStudentRegService studentRegService;

    @Resource
    private IConfigService configService;


    @Override
    public SuggestResultVo suggestContinueClass(Long studentId){
        List<ContinueClassSuggestResultVo> suggest = continueClassSuggestionService.suggest(studentId);
        if(suggest == null || suggest.isEmpty() ){
            return null;
        }

        Map<Integer,List<ContinueClassSuggestResultVo>> priority2ContinueClassSuggestResultVo =  BeanUtils.toGroup(suggest,"priority");
        List<Long> classIds = BeanUtils.toList(suggest,"classId");
        List<OuterCourseClass> outerCourseClasses = outerCourseClassService.findByClassIds(classIds);
        Map<Long,OuterCourseClass> classId2OuterCourseClass = BeanUtils.toMap(outerCourseClasses,"classId");
        List<ContinueClassSuggestResultVo> continueClassSuggestResultVos1 = priority2ContinueClassSuggestResultVo.get(1);
        List<ContinueClassSuggestResultVo> continueClassSuggestResultVos2 = priority2ContinueClassSuggestResultVo.get(2);
        SuggestResultVo suggestResultVo = new SuggestResultVo();

        if(continueClassSuggestResultVos1 != null ){
            List<OuterCourseClass> baseSuggests = new ArrayList<>(continueClassSuggestResultVos1.size());
            for(ContinueClassSuggestResultVo continueClassSuggestResultVo : continueClassSuggestResultVos1){
                OuterCourseClass outerCourseClass = classId2OuterCourseClass.get(continueClassSuggestResultVo.getClassId());
                if(outerCourseClass != null ){
                    baseSuggests.add(outerCourseClass);
                }
            }
            suggestResultVo.setBaseSuggests(baseSuggests);
        }


        if(continueClassSuggestResultVos2 != null ){
            List<OuterCourseClass> moreSuggests = new ArrayList<>(continueClassSuggestResultVos2.size());
            for(ContinueClassSuggestResultVo continueClassSuggestResultVo : continueClassSuggestResultVos2){
                OuterCourseClass outerCourseClass = classId2OuterCourseClass.get(continueClassSuggestResultVo.getClassId());
                if(outerCourseClass != null ){
                    moreSuggests.add(outerCourseClass);
                }
            }
            suggestResultVo.setMoreSuggests(moreSuggests);
        }

        return suggestResultVo ;

    }


    @Override
    public List<OuterCourseClass> suggestCourseClassByClass(Long classId) {
        //同校区、同年级、同层级、不同科目（随机显示三个符合条件的课程；若不够三个，则显示一个或两个；若一个科目都没有，则不显示推荐）
        CourseClass courseClass = courseClassService.findById(classId);

        Query query = new Query();
        query.addCriteria(Criteria.where("campusId").is(courseClass.getCampusId()));
        query.addCriteria(Criteria.where("periodId").is(courseClass.getPeriodId()));
        query.addCriteria(Criteria.where("gradeId").is(courseClass.getGradeId()));
        query.addCriteria(Criteria.where("subjectId").ne(courseClass.getSubjectId()));
        query.addCriteria(Criteria.where("level").is(courseClass.getLevel()));
        query.addCriteria(Criteria.where("status").is(1));//已开班课程
        query.addCriteria(Criteria.where("progressStatus").in(0,1));//未开课课程、已开课

        List<OuterCourseClass> alls = mongoTemplate.find(query,OuterCourseClass.class);

        Map<Long, List<OuterCourseClass>> subjectId2OuterCourseClassGroup = BeanUtils.toGroup(new ArrayList<>(Collections2.filter(alls,input -> !input.getClassId().equals(classId))), "subjectId");

        List<OuterCourseClass> ret = new ArrayList<>(5);

        for(Map.Entry<Long, List<OuterCourseClass>> entry : subjectId2OuterCourseClassGroup.entrySet() ){
            ret.add(entry.getValue().get(0));
            if(ret.size() >= 3 ){
                break;
            }
        }
        return ret;
    }


    @Override
    public List<OuterCourseClass> suggestCourseClass(Long areaTeamId , Double longitude, Double latitude, Long userId) {

        CourseDisplayConfig courseDisplayConfig = configService.findCourseDisplayConfig(areaTeamId);

        if(courseDisplayConfig == null || courseDisplayConfig.getPeriods() == null ){
            return Collections.EMPTY_LIST ;
        }

        List<Long> periodIds = Lists.transform(courseDisplayConfig.getPeriods(),p -> p.getPeriodId() );


        CourseClass recentInterest = null ;

        if(userId != null ){
            OuterShoppingcart shoppingcart = outerShoppingcartService.findOneRecent(userId);
            if(shoppingcart != null ){
                recentInterest = courseClassService.findById(shoppingcart.getClassId(),"gradeId","campusId");
            }
        }

        if(recentInterest == null && userId != null ){
            OuterOrder outerOrder = outerOrderService.findOneRecent(userId);
            if(outerOrder != null ){
                Example<StudentReg> studentRegExample = StudentReg.createExample();
                studentRegExample.selectProperties("classId");
                studentRegExample.createCriteria().andEqualTo("courseOrderId",Long.valueOf(outerOrder.getSubOrderIds().split(",")[0]));
                StudentReg studentReg = studentRegService.findOneByExample(studentRegExample);
                recentInterest = courseClassService.findById(studentReg.getClassId(),"gradeId","campusId") ;
            }
        }

        Query query = new Query();
        if(periodIds != null){
            query.addCriteria(Criteria.where("periodId").in(periodIds)) ;
        }

        if(recentInterest != null){
            query.addCriteria(Criteria.where("gradeId").is(recentInterest.getGradeId()));
            query.addCriteria(Criteria.where("campusId").is(recentInterest.getCampusId()));
        }else{
            if(longitude != null && latitude != null ){
                OuterCampus outerCampus = campusService.findOneNearest(longitude, latitude);
                query.addCriteria(Criteria.where("campusId").is(outerCampus.getCampusId()));
            }
        }

        query.addCriteria(Criteria.where("status").is(1));//已开班课程

        List<OuterCourseClass> alls = mongoTemplate.find(query,OuterCourseClass.class);

        Map<String,List<OuterCourseClass>> key2OuterCourseClass = BeanUtils.toGroup(alls, new Function<OuterCourseClass, String>() {
            @Override
            public String apply(OuterCourseClass input) {
                return StringUtils.EMPTY + input.getPeriodId() + input.getGradeId() +  input.getSubjectId() ;
            }
        });

        List<OuterCourseClass> suggests = new ArrayList<>();
        for(Map.Entry<String,List<OuterCourseClass>> entry : key2OuterCourseClass.entrySet() ){
            Collections.sort(entry.getValue(), new Comparator<OuterCourseClass>() {
                @Override
                public int compare(OuterCourseClass o1, OuterCourseClass o2) {
                    if(o1.getLevel() == null || o2.getLevel() == null ){
                        return 0 ;
                    }
                    return o2.getLevel().compareTo(o1.getLevel());
                }
            });
            suggests.add(entry.getValue().get(0));
        }

        return suggests;
    }

}
